package com.wei.entity;


import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

public class NodeUtil {

    private List<Node> treeList = new ArrayList<>();

    private List<Node> removeList = new ArrayList<>();

    private int index = 0;

    private final static int defaultParentIndex = -1;

    private final static int defaultLeft = 1;

    private final static int defaultRight = 2;

    private final static int defaultLevel = 1;

    private final static int defaultValueSpace = 2;

    public List<Node> getTreeList(){
        return removeList;
    }

    public static void main(String[] args) {
        NodeUtil nodeUtil = new NodeUtil();
        nodeUtil.addNode("A");
        nodeUtil.addNode(nodeUtil.getNode("A").getIndex(),"B");
        nodeUtil.addNode(nodeUtil.getNode("B").getIndex(),"C");
        nodeUtil.addNode(nodeUtil.getNode("C").getIndex(),"D");
        nodeUtil.addNode(nodeUtil.getNode("B").getIndex(),"E");
        nodeUtil.addNode(nodeUtil.getNode("E").getIndex(),"F");

        nodeUtil.addNode(nodeUtil.getNode("A").getIndex(),"G");
        nodeUtil.addNode(nodeUtil.getNode("G").getIndex(),"H");
        nodeUtil.addNode(nodeUtil.getNode("H").getIndex(),"I");
        nodeUtil.addNode(nodeUtil.getNode("H").getIndex(),"J");


        nodeUtil.addNode(nodeUtil.getNode("A").getIndex(),"K");
        nodeUtil.addNode(nodeUtil.getNode("K").getIndex(),"L");

        System.out.println(JSON.toJSONString(nodeUtil.treeList));
    }

    public List<Node> getAllChildList(Object value){
        Node node = this.getNode(value);
        return treeList.stream().filter(n-> n.left > node.getLeft() && n.right < node.getRight()).collect(Collectors.toList());
    }

    public List<Node> getChildList(Object value){
        Node node = this.getNode(value);
        return treeList.stream().filter(n-> n.left > node.getLeft() && n.right < node.getRight() && n.level == node.level + 1).collect(Collectors.toList());
    }


    public Node getParent(Object value){
        Node node = this.getNode(value);
        return this.getNode(node.parentIndex);
    }

    public int size(){
        return treeList.size();
    }

    public void moveNode(Object value,Object targetValue){
        Node node = this.getNode(value);
        Node targetNode = this.getNode(targetValue);
        this.removeNode(value);
        removeList.remove(node);
        this.addNode(node.index,targetNode,value);
        for (Node n:removeList) {
            this.addNode(n.parentIndex,n.value);
        }
        treeList = treeList.stream().sorted(Comparator.comparing(Node::getIndex)).collect(Collectors.toList());
    }


    public Node getNode(Object value){
        Optional<Node> optionalNode = treeList
                .stream()
                .filter(n->value.equals(n.value)).findFirst();
        return optionalNode.orElse(null);
    }


    private Node getNode(int index){
        Optional<Node> optionalNode = treeList
                .stream()
                .filter(n->index == n.index).findFirst();
        return optionalNode.orElse(null);
    }

    public void addNode(int index ,Node targetNode, Object value){
        Node node = new Node(index, value ,targetNode.right , targetNode.right + 1, targetNode.level + 1 ,targetNode.index);
        this.vindicateNode(targetNode.right,defaultValueSpace);
        treeList.add(node);
    }

    public void addNode(Object value){
        this.addNode(index,value);
    }

    public void addNode(int index , Object value){
        //根据index获取node
        Node parentNode = this.getNode(index);
        //如果node为空则当前node为根节点
        if(ObjectUtils.isEmpty(parentNode)){
            //生成根节点Node
            parentNode = new Node(index,value);
            treeList.add(parentNode);
            return;
        }
        //否则添加子节点
        //index = list.length
        //left = parentNode.right
        //right = parentNode.right + 1
        //level = parentNode.level + 1
        Node node = new Node(treeList.size(), value ,parentNode.right , parentNode.right + 1, parentNode.level + 1 ,parentNode.index);
        //维护其他节点
        this.vindicateNode(parentNode.right,defaultValueSpace);
        treeList.add(node);
    }


    private void vindicateNode(int right, int valueSpace) {
        List<Node> nodes = new ArrayList<>();
        for (Node n : treeList) {
            //left>=父right的node值自增valueSpace
            if(n.left >= right){
                n.left += valueSpace;
            }
            //right>=父right的node值自增valueSpace
            if(n.right >= right){
                n.right += valueSpace;
            }
            nodes.add(n);
        }
        treeList = nodes.stream().sorted(Comparator.comparing(Node::getIndex)).collect(Collectors.toList());
    }
    public void removeNode(Object value){
        Node node = this.getNode(value);
        int size = this.size();
        for (int i = 0; i < size; i++) {
            Node n = treeList.get(i);
            if(n.left >= node.left && n.right <= node.right){
                removeList.add(n);
            }
        }
        treeList.removeAll(removeList);
        int valueSpace = node.right - node.left + 1;
        List<Node> nodes = new ArrayList<>();
        for (Node n : treeList) {
            if(n.left > node.left){
                n.left -= valueSpace;
            }
            if(n.right > node.right){
                n.right -= valueSpace;
            }
            nodes.add(n);
        }
        treeList = nodes.stream().sorted(Comparator.comparing(Node::getIndex)).collect(Collectors.toList());
    }



    public int childNodeNumber(Node node){
        return (node.right - node.left - 1) / 2;
    }

    static class Node{

        private int index;

        private int parentIndex;

        private Object value;

        private int left;

        private int right;

        private int level;

        public Node(int index,Object value){
            this.index = index;
            this.value = value;
            this.left = defaultLeft;
            this.right = defaultRight;
            this.level = defaultLevel;
            this.parentIndex = defaultParentIndex;
        }

        public Node(int index,Object value,int left,int right,int level,int parentIndex){
            this.index = index;
            this.value = value;
            this.left = left;
            this.right = right;
            this.level = level;
            this.parentIndex = parentIndex;
        }

        public int getParentIndex() {
            return parentIndex;
        }

        public void setParentIndex(int parentIndex) {
            this.parentIndex = parentIndex;
        }

        public int getIndex() {
            return index;
        }

        public void setIndex(int index) {
            this.index = index;
        }

        public Object getValue() {
            return value;
        }

        public void setValue(Object value) {
            this.value = value;
        }

        public int getLeft() {
            return left;
        }

        public void setLeft(int left) {
            this.left = left;
        }

        public int getRight() {
            return right;
        }

        public void setRight(int right) {
            this.right = right;
        }

        public int getLevel() {
            return level;
        }

        public void setLevel(int level) {
            this.level = level;
        }
    }
}
